package com.validant.enigma3.controls;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.testng.Assert;

import com.validant.enigma3.common.Constants;
import com.validant.enigma3.common.Constants.Selector;
import com.validant.enigma3.common.Utils;

public class ExtWebElement {
	
	protected WebElement element;
	
	public ExtWebElement(WebElement element){
		this.element = element;
	}
	
	public ExtWebElement(WebDriver driver, By locator){
		try {			
			this.element = driver.findElement(locator);
		} catch (Exception e) {
			Assert.assertTrue(false);
		}
	}
	
	/**********************************************************
	 * WRAP-UP WEB ELEMENT'S FUNCTIONS 
	 **********************************************************/
	/*
	 * wrap up WebElement's function
	 */
	public boolean isSelected() {
		return element.isSelected();
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public boolean isEnabled() {
		return element.isEnabled();
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public boolean isDisplayed() {
		return element.isDisplayed();
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public String getText() {
		return element.getText();
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public String getTagName() {
		return element.getTagName();
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public Dimension getSize() {
		return element.getSize();
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public Point getLocation() {
		return element.getLocation();
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public String getCssValue(String arg0) {
		return element.getCssValue(arg0);
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public String getAttribute(String attribute) {
		return element.getAttribute(attribute);
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public ExtWebElement findElement(By locator) {
		ExtWebElement retElement = new ExtWebElement(element.findElement(locator));
		return retElement;
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public ExtWebElement findElement(Selector selector, String path) {
		ExtWebElement retElement = new ExtWebElement(element.findElement(Utils.getLocator(selector, path)));
		return retElement;
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public List<ExtWebElement> findElements(By locator) {
		return Utils.toExtWebElements(element.findElements(locator));
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public List<ExtWebElement> findElements(Selector selector, String path) {
		return Utils.toExtWebElements(element.findElements(Utils.getLocator(selector, path)));
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public void submit() {
		if (isAvailableForAction())
			element.submit();
		else
			Assert.assertTrue(false);	
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public void sendKeys(CharSequence... key) {
		if (isAvailableForAction())
			element.sendKeys(key);
		else
			Assert.assertTrue(false, Constants.ERR_MSG_NOT_AVAILABLE_TO_ACTION);
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public void click() {
		if (isAvailableForAction())
			element.click();
		else
			Assert.assertTrue(false, Constants.ERR_MSG_NOT_AVAILABLE_TO_ACTION);
	}
	
	/*
	 * wrap up WebElement's function
	 */
	public void clear() {
		if (isAvailableForAction())
			element.clear();
		else
			Assert.assertTrue(false, Constants.ERR_MSG_NOT_AVAILABLE_TO_ACTION);
	}
	
	/**********************************************************
	 * OTHER ADDED NEW FUNCTIONS
	 **********************************************************/
	/*
	 * return its cored web element control
	 */
	public WebElement getWebElement() {
		return element;
	}
	
	/*
	 * remove an attribute of web element
	 * for example: remove READONLY attribute 
	 * 				removeAttribute(driver, "readonly")
	 */
	public void removeAttribute(ExtWebDriver driver, String attribute) {
		String JSScript = "arguments[0].removeAttribute('" + attribute + "');";
		((JavascriptExecutor)driver.getWebDriver()).executeScript(JSScript, element);
	}
	
	/**********************************************************
	 * VERIFYING FUNCTIONS
	 **********************************************************/
	
	/*
	 * check whether a control is present or not
	 */
	public boolean isPresent() {
		if (element != null)
			return true;
		else
			return false;
	}
	
	/*
	 * check whether a control is present, visible and enable
	 */
	public boolean isAvailableForAction() {
		if (isPresent() && isDisplayed() && isEnabled())
			return true;
		else
			return false;
	}
	
	/*
	 * verify whether a control is present or not 
	 */
	public void verifyIsPresent() {
		if (isPresent())
			Assert.assertTrue(true);
		else
			Assert.assertTrue(false);
	}
	
	/*
	 * verify whether a control is not present 
	 */
	public void verifyIsNotPresent() {
		if (!isPresent())
			Assert.assertTrue(true);
		else
			Assert.assertTrue(false);
	}
	
	/*
	 * verify whether a control is visible or not 
	 */
	public void verifyIsVisible() {
		if (isPresent() && isDisplayed())
			Assert.assertTrue(true);
		else
			Assert.assertTrue(false);
	}
	
	/*
	 * verify whether a control is not visible 
	 */
	public void verifyIsNotVisible() {
		if (!isPresent())
			Assert.assertTrue(false, Constants.ERR_MSG_ELEMENT_NOT_FOUND);
		
		if (!isDisplayed())
			Assert.assertTrue(true);
		else
			Assert.assertTrue(false);
	}
	
	/*
	 * verify whether a control is enable or not 
	 */
	public void verifyIsEnabled() {
		if (isPresent() && isDisplayed() && isEnabled())
			Assert.assertTrue(true);
		else
			Assert.assertTrue(false);
	}
	
	/*
	 * verify whether a control is enable or not 
	 */
	public void verifyIsNotEnabled() {
		if (!isPresent())
			Assert.assertTrue(false, Constants.ERR_MSG_ELEMENT_NOT_FOUND);
		
		if (!isDisplayed())
			Assert.assertTrue(false, Constants.ERR_MSG_ELEMENT_HIDDEN);		
		
		if (!isEnabled())
			Assert.assertTrue(true);
		else
			Assert.assertTrue(false);
	}
	
	/*
	 * verify whether an attribute of a control equals a value   
	 */
	public void verifyAttributeEquals(String attribute, String value) {
		Assert.assertTrue(element.getAttribute(attribute).equals(value));
	}
	
	/*
	 * verify whether an attribute of a control contains a value 
	 */
	public void verifyAttributeContains(String attribute, String value) {
		Assert.assertTrue(element.getAttribute(attribute).contains(value));
	}
	
	/*
	 * verify whether control's text contains a value 
	 */
	public void verifyTextEquals(String value) {
		Assert.assertTrue(element.getText().equals(value));
	}
	
	/*
	 * verify whether control's text contains a value 
	 */
	public void verifyTextContains(String value) {
		Assert.assertTrue(element.getText().contains(value));
	}
	
}
